﻿#!/usr/bin/env python
# -*- coding: utf-8 -*-

# bios.py

# Copyright 2009 Diego Hansen Hahn (aka DiegoHH) <diegohh90 [at] hotmail [dot] com>

# lazynds is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License.

# lazynds is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with lazynds. If not, see <http://www.gnu.org/licenses/>.

''' Wrapper para as rotinas de compressão da BIOS '''

import os
import struct

import gtk

from compression import (lzss, rle, huffman)
import pluginmanager

class bios(object):

	# Atributos padrões
	MIN_SIZE = 0x20
	MAX_SIZE = 0xFFFF
	MULTIPLE = 0x20

	def __init__(self, fd, info = None):
		self.props = False
		self.fd = fd

		self.decode_list = []

	def set_decode_mode(self, mode):
		self.decode_mode = mode

	def is_decode_mode(self, mode):
		if hasattr(self, 'decode_mode'):
			return self.decode_mode.__eq__(mode)
		else:
			return False

	def scan(self, progbar):
		self.fd.seek(0, 0)
		file_map = self.fd.read()
		file_size = len(file_map)
		i = 0
		c = 0

		results = []

		while True:
			try:
				while gtk.events_pending():
					gtk.main_iteration()
				while ord(file_map[i]) & 0xF0 not in self.decode_list:
					i += 4
				header = struct.unpack('<L', file_map[i:i+4])[0]
				size = header >> 8
				flag = header & 0xFF
				if (size % self.MULTIPLE == 0
				and size <= self.MAX_SIZE
				and size >= self.MIN_SIZE):
					if flag == 0x10 and lzss.try_uncompress(file_map, i, size):
						results.append((i, 0x10))
					elif flag == 0x30 and rle.try_uncompress(file_map, i, size):
						results.append((i, 0x30))
					elif flag == 0x24 and huffman.try_uncompress(file_map, i, size):
						results.append((i, 0x24))
					elif flag == 0x28 and huffman.try_uncompress(file_map, i, size):
						results.append((i, 0x28))
				if i > int(c * file_size):
					percent = float(i)/file_size
					progbar.set_text('Buscando: ' + str(int(percent * 100)) + "%")
					progbar.set_fraction(percent)
					c += 0.1
				i += 4
			except:
				break

		progbar.set_text('Concluído: 100%')
		progbar.set_fraction(1.0)
		while gtk.events_pending():
			gtk.main_iteration()

		return results

	def uncompress(self, address, type):
		if type == 0x10:
			buffer = lzss.uncompress(self.fd, address)
		elif type == 0x30:
			buffer = rle.uncompress(self.fd, address)
		elif (type == 0x24) or (type == 0x28):
			buffer = huffman.uncompress(self.fd, address)
		return buffer

	def compress(self, infile, type):
		if self.is_decode_mode(0x10):
			return lzss.compress(infile)
		elif self.is_decode_mode(0x30):
			return rle.compress(infile)
		#elif self.is_decode_mode(0x24):
		#	return huffman.compress(infile, 4)
		elif self.is_decode_mode(0x28):
			return huffman.compress(infile, 8)
